﻿using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;

namespace RemotingGuidance
{
    [Serializable]
    public abstract class Guidance : MarshalByRefObject
    {
        public static IChannel[] RegistredChannels { get { return ChannelServices.RegisteredChannels; } }

        public static void RegisterChannel(IChannel Channel, bool Security = false) { Channel.Register(Security); }

        public static void UnRegisterChannel(IChannel Channel) { Channel.UnRegister(); }

        public static WellKnownServiceTypeEntry RegisterServer<T>(string Uri = null,
            WellKnownObjectMode Mode = WellKnownObjectMode.Singleton)
        //where T : Guidance
        {
            var type = typeof(T);
            if(string.IsNullOrEmpty(Uri))
                Uri = type.FullName;
            Debug.Assert(Uri != null, "Uri != null");
            var entry = new WellKnownServiceTypeEntry(type, Uri, Mode);
            RemotingConfiguration.RegisterWellKnownServiceType(entry);
            return entry;
        }

        public static WellKnownServiceTypeEntry RegisterServer<T>(IChannel Channel, bool Security = false,
            string Uri = null, WellKnownObjectMode Mode = WellKnownObjectMode.Singleton)
        //where T : Guidance
        {
            //IpcChannel
            RegisterChannel(Channel, Security);
            return RegisterServer<T>(Uri, Mode);
        }

        public static T Create<T>(IChannel Channel, bool Security, string URL)
        //where T : Guidance
        {
            if(!Array.Exists(RegistredChannels, c => c == Channel))
                RegisterChannel(Channel, Security);
            if(!Array.Exists(RemotingConfiguration.GetRegisteredWellKnownClientTypes(),
                e => e.ObjectUrl == URL))
                RegisterClient<T>(Channel, Security, URL);
            return Create<T>(URL);
        }

        public static WellKnownClientTypeEntry RegisterClient<T>(IChannel Channel, bool Security,
            string Uri)
        //where T : Guidance
        {
            if(!Array.Exists(RegistredChannels, c => c == Channel))
                RegisterChannel(Channel, Security);
            var entry = new WellKnownClientTypeEntry(typeof(T), Uri);
            RemotingConfiguration.RegisterWellKnownClientType(entry);
            return entry;
        }

        public static T Create<T>(string URL) /* where T : Guidance */ { return (T)Activator.GetObject(typeof(T), URL); }
    }
}
